#include <qDebug>
#include <QDir>
#include <QFile>
#include <QFileDialog>
#include <QTemporaryFile>
#include <QThread>

#include <QMessageBox>
#include <QSqlDatabase>
#include <QSqlError>
#include <QSqlQuery>
#include <ctime>
#include <random>
#include<chrono>
#include "qtwordfetch.h"

QtWordFetch::QtWordFetch(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);

    connect(&_process, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(onfinished(int, QProcess::ExitStatus)));
    connect(&_process, SIGNAL(errorOccurred(QProcess::ProcessError)), this, SLOT(onerrorOccurred(QProcess::ProcessError)));
    connect(&_process, SIGNAL(started()), this, SLOT(onstarted()));
}

QtWordFetch::~QtWordFetch()
{

}

void QtWordFetch::Transform(QString input, QString output, QString lang)
{
    QStringList arguments;
    arguments << "-l" << lang << input << output << "-v";

    QString filePath = "./lemmatize.exe";
    qDebug() << QDir::currentPath();
    _process.start(filePath, arguments);
}

void QtWordFetch::StatisticsWord(QString filePath, QMap<QString, int> &result)
{
    QFile file(filePath);
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        return;
    }

    QString allString = QString(file.readAll());
    QStringList list = allString.split(QRegExp("\\W+"), QString::SkipEmptyParts);

    for (int i = 0; i < list.size(); i++)
    {
        stringModify(list[i]);
        if (stringFilter(list[i]) == true)
        {
            continue;
        }

        result[list[i]] += 1;
    }
    file.close();
}

void QtWordFetch::stringModify(QString &str)
{
    str = str.toLower();
}

bool QtWordFetch::stringFilter(QString str)
{
    bool ret = false;
    if (str.length() < 4)
    {
        return true;
    }
    str.toDouble(&ret);
    if (ret == true)
    {
        return true;
    }

    return false;
}

void  QtWordFetch::onfinished(int exitCode, QProcess::ExitStatus exitStatus)
{
    qDebug() << "QtWordFetch::onfinished:" << exitCode << exitStatus;
    if (exitCode == 0)
    {
        QMap<QString, int> result;
        StatisticsWord("output.txt", result);

        QFile file("output.txt");
        if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
        {
            return;
        }

        QString allString = QString(file.readAll());
        ui.textEdit_output->setText(allString);
        file.close();

        ui.textEdit_result->clear();
        //for (QMap<QString, int>::iterator it = result.begin(); it != result.end(); it++)
        //{
        //    ui.textEdit_result->append(it.key().toStdString().c_str());
        //}

        QVector<QString> sortRes;
        QVector<int> indexs;
        for (QMap<QString, int>::iterator it = result.begin(); it != result.end(); it++)
        {
            sortRes.push_back(it.key());
        }
        //
        for (int i = 0; i < sortRes.size(); i++)
        {
            indexs.push_back(i);
        }

        unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
        std::shuffle(indexs.begin(), indexs.end(), std::default_random_engine(seed));

        for (int i = 0; i < indexs.size(); i++)
        {
            ui.textEdit_result->append(sortRes[indexs[i]]);;
        }
    }
}

void  QtWordFetch::onerrorOccurred(QProcess::ProcessError error)
{
    qDebug() << QDir::currentPath() << error;
}

void  QtWordFetch::onstarted()
{
    qDebug() << "onstarted";
    QThread::msleep(50);
}

void QtWordFetch::on_pushButton_inputData_clicked()
{
}

void QtWordFetch::on_pushButton_Statistics_clicked()
{
    qDebug() << "on_pushButton_Statistics_clicked";
    //Transform("input.txt", "output.txt", "E:\\Project\\LemmaGen_v2.2\\v2.2\\data\\lemmatizer\\lem-me-en.bin");

    QString input = ui.textEdit_input->toPlainText();
    QTemporaryFile file;
    if (file.open())
    {
        file.write(input.toStdString().c_str());
        file.close();

        if (file.exists())
        {
            Transform(file.fileName(), "output.txt", "./lem-me-en.bin");
        }
    }
}
int QtWordFetch::GetStringsFromFile(QString fileName)
{
    QFile file(fileName);

    if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        return 0;
    }

    QString allFileData;
    allFileData.append(file.readAll());
    int index = 0;
    QRegularExpression regularExpression("\\b\\w+\\b");
    QRegularExpressionMatch match;
    do
    {
        match = regularExpression.match(allFileData, index);
        if(match.hasMatch())
        {
            index = match.capturedEnd();
            //list << match.captured(0);

            if(wordMap.find(match.captured(0)) == wordMap.end())
            {
                wordMap[match.captured(0)] =0;
            }
        }
        else
            break;
    }
    while(index < allFileData.length());

    file.close();
    return wordMap.size();
}

void QtWordFetch::on_pushButton_outPut_clicked()
{
    qDebug() << "on_pushButton_outPut_clicked";


    QString fileName = QFileDialog::getOpenFileName(this,
                       tr("保存结果"), "./");

    if (fileName.length() > 0)
    {
        QDir dir;
        QString currentPath = QCoreApplication::applicationDirPath();
        dir.setPath(currentPath+"/output/");

        QStringList filters;
        filters << "*.txt";
        QStringList files = QDir(dir).entryList(filters);
        for(int i = 0; i < files.size(); i++)
        {
            int size = GetStringsFromFile(currentPath+"/output/"+files[i]);
            qDebug() << size << currentPath+"/output/"+files[i];
        }
        QFile file(fileName);
        file.open(QIODevice::WriteOnly);
        QDataStream out(&file);   // we will serialize the data into the file
        out << wordMap; //
        wordMap.clear();
        file.close();
    }
}

bool QtWordFetch::createConnection()
{
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName(":memory:");
    if (!db.open())
    {
        QMessageBox::critical(0, qApp->tr("Cannot open database"),
                              qApp->tr("Unable to establish a database connection.\n"
                                       "This example needs SQLite support. Please read "
                                       "the Qt SQL driver documentation for information how "
                                       "to build it.\n\n"
                                       "Click Cancel to exit."), QMessageBox::Cancel);
        return false;
    }

    //QSqlQuery query;
    //query.exec("create table person (id int primary key, "
    //           "firstname varchar(20), lastname varchar(20))");
    //query.exec("insert into person values(101, 'Danny', 'Young')");
    //query.exec("insert into person values(102, 'Christine', 'Holand')");
    //query.exec("insert into person values(103, 'Lars', 'Gordon')");
    //query.exec("insert into person values(104, 'Roberto', 'Robitaille')");
    //query.exec("insert into person values(105, 'Maria', 'Papadopoulos')");

    return true;
}

bool QtWordFetch::createDbData(QMap<QString, int> &data)
{
    QSqlQuery query;
    query.exec("create table staticsWord (id int primary key, "
               "word varchar(20), counts int");
    for (QMap<QString, int>::iterator it = data.begin(); it != data.end(); it++)
    {
        QString sql = QString("");

        query.exec("insert into staticsWord values(101, 'Danny', 'Young')");

    }
    query.exec("insert into person values(102, 'Christine', 'Holand')");
    query.exec("insert into person values(103, 'Lars', 'Gordon')");
    query.exec("insert into person values(104, 'Roberto', 'Robitaille')");
    query.exec("insert into person values(105, 'Maria', 'Papadopoulos')");

    return false;
}
void QtWordFetch::initializeModel(QSqlTableModel *model)
{
    model->setTable("person");
    model->setEditStrategy(QSqlTableModel::OnManualSubmit);
    model->select();

    model->setHeaderData(0, Qt::Horizontal, QObject::tr("ID"));
    model->setHeaderData(1, Qt::Horizontal, QObject::tr("First name"));
    model->setHeaderData(2, Qt::Horizontal, QObject::tr("Last name"));

    qDebug() << model->record().count();
    qDebug() << model->record().fieldName(0);
    qDebug() << model->record().fieldName(1);
    qDebug() << model->record().fieldName(2);
}
